﻿using FreeSql;
using FreeSql.Aop;
using System.Reflection;
using System.Security.Claims;
using Yitter.IdGenerator;


namespace Wen.GrpcService.Extensions;

public static class FreeSqlServiceExtension
{
    public static IServiceCollection AddFreeSqlServices(this IServiceCollection services)
    {
        services.AddSingleton(provider =>
        {
            var httpContextAccessor = provider.GetService<IHttpContextAccessor>()!;
            var configuration = provider.GetRequiredService<IConfiguration>();

            var connString = configuration.GetConnectionString("DefaultConnection");

            var dbType = Enum.TryParse(configuration.GetConnectionString("DbType"), out DataType result) ? result : DataType.Sqlite;

            IFreeSql fsql = new FreeSql.FreeSqlBuilder()
                .UseConnectionString(dbType, connString)
                .UseAdoConnectionPool(true)
#if DEBUG
                .UseMonitorCommand(cmd => Console.WriteLine($"Sql：{cmd.CommandText}"))
                .UseAutoSyncStructure(true) //自动同步实体结构到数据库，只有CRUD时才会生成表
#endif
                .CreateDatabaseIfNotExistsSqlServer()
                .Build();

            fsql.Aop.AuditValue += (s, e) =>
            {
                if (e.Column.CsType == typeof(long) &&
                    e.Property.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>(false) != null &&
                    e.Value?.ToString() == "0")
                    e.Value = YitIdHelper.NextId();

                if (e.AuditValueType == AuditValueType.Insert)
                {
                    if (e.Column.CsName == "CreateTime")
                    {
                        e.Value = DateTime.Now;
                    }
                    else if (e.Column.CsName == "CreateUserName")
                    {
                        e.Value = httpContextAccessor?.HttpContext?.User?.Identity?.Name ?? "System";
                    }
                }
                else if (e.AuditValueType == AuditValueType.Update)
                {
                    if (e.Column.CsName == "UpdateTime")
                    {
                        e.Value = DateTime.Now;
                    }
                    else if (e.Column.CsName == "UpdateUserName")
                    {
                        e.Value = httpContextAccessor?.HttpContext?.User?.Identity?.Name ?? "System";
                    }
                }

            };

            fsql.Aop.ConfigEntityProperty += (s, e) =>
            {
                if (e.Property.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() is not null)
                    e.ModifyResult.IsPrimary = true; //Key
            };

            return fsql;
        });
        return services;
    }
}
